package com.gator.spring.framework.aop;

import com.gator.spring.framework.aop.intercept.PABLO_MethodInvocation;
import com.gator.spring.framework.aop.support.PABLO_AdvisedSupport;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * @Author PABLO
 * @Date 2022/5/8 13:34
 * @Desc JDK动态代理
 */
public class PABLO_JdkDynamicAopProxy implements PABLO_AopProxy, InvocationHandler {

    //回调通知的扩展   切点被执行时会回调代理，即调用这里的invoke
    private PABLO_AdvisedSupport advised;

    public PABLO_JdkDynamicAopProxy(PABLO_AdvisedSupport config) {
        this.advised = config;
    }

    @Override
    public Object getProxy() {
        return getProxy(this.advised.getTargetClass().getClassLoader());
    }

    /**
     * @Description: 创建代理对象
     * @Author: PABLO
     * @Date: 2022/5/9 12:36
     * @Params: [classLoader]
     * @Return: java.lang.Object
     **/
    @Override
    public Object getProxy(ClassLoader classLoader) {
            return Proxy.newProxyInstance(classLoader, this.advised.getTargetClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //通过method(key)获得该切点的拦截器链
        //每个方法和对应的执行器链保存在map中，Map<Method,List<PABLO_MethodInterceptor> chain
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, this.advised.getTargetClass());
        //构建执行拦截器链对象，会依次执行链条上的方法
        PABLO_MethodInvocation invocation = new PABLO_MethodInvocation(proxy, this.advised.getTarget(), method, args, this.advised.getTargetClass(), chain);
        //执行拦截器链，proceed执行完链条上所有节点后会执行真正的目标方法
        return invocation.proceed();
    }
}
